﻿using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using IceDog.DNF.Program.Ef6.EfContext;
using IceDog.DNF.Program.Ef6.Models;
using Newtonsoft.Json;

namespace IceDog.DNF.Program.Ef6.CLi.Client
{
    class Program
    {
        static void Main(string[] args)
        {
            //TestDefaultEfAction();
            //TestCreateDbByOrderContext();

            //TestDropCreateDatabaseAlways();
            //TestCreateDatabaseIfNotExists();
            //TestDropCreateDatabaseIfModelChanges();

            TestEfConcurrency();
        }

        //ef默认行为
        static void TestDefaultEfAction()
        {
            using (var ctx = new OrderContext())
            {
                if (ctx.Orders.Count() < 10)
                {
                    var orders = Enumerable.Range(1, 10).Select(i => new Order
                    {
                        Customer = "sammy" + i,
                        OrderDate = DateTime.Now,
                    });
                    ctx.Orders.AddRange(orders);
                    ctx.SaveChanges();
                }
                var query = from order in ctx.Orders
                            select order;
                foreach (var q in query)
                {
                    Console.WriteLine("OrderId:{0}\tOrderDate:{1}", q.Id, q.OrderDate);
                }
            }
        }

        static void TestCreateDbByOrderContext()
        {
            using (var ctx = new OrderContext("OrderContext"))
            {
                if (ctx.Orders.Count() < 10)
                {
                    var orders = Enumerable.Range(1, 10).Select(i => new Order
                    {
                        Customer = "sammy" + i,
                        OrderDate = DateTime.Now,
                    });
                    ctx.Orders.AddRange(orders);
                    ctx.SaveChanges();
                }
                var query = from order in ctx.Orders
                            select order;
                foreach (var q in query)
                {
                    Console.WriteLine("OrderId:{0}\tOrderDate:{1}", q.Id, q.OrderDate);
                }
            }
        }

        /// <summary>
        /// 此处每次运行都会创建新的数据库
        /// </summary>
        private static void TestDropCreateDatabaseAlways()
        {
            var strategy = new OrderInitializerForDropCreateDatabaseAlways();
            Database.SetInitializer<OrderContext>(strategy);
            using (OrderContext context = new OrderContext())
            {
                var json = JsonConvert.SerializeObject(context.Orders.ToList(), Formatting.Indented);
                Console.WriteLine(json);
            }
        }
        /// <summary>
        /// 此处只有第一次运行才会创建新的数据库
        /// </summary>
        private static void TestCreateDatabaseIfNotExists()
        {
            var strategy = new OrderInitializerForCreateDatabaseIfNotExists();
            Database.SetInitializer<OrderContext>(strategy);
            using (OrderContext context = new OrderContext())
            {
                var json = JsonConvert.SerializeObject(context.Orders.ToList(), Formatting.Indented);
                Console.WriteLine(json);
            }

        }
        /// <summary>
        /// 测试此处需要修改Order模型，修改模型运行才会创建新的数据库
        /// </summary>
        private static void TestDropCreateDatabaseIfModelChanges()
        {
            var strategy = new OrderInitializerForDropCreateDatabaseIfModelChanges();
            Database.SetInitializer<OrderContext>(strategy);
            using (OrderContext context = new OrderContext())
            {
                var json = JsonConvert.SerializeObject(context.Orders.ToList(), Formatting.Indented);
                Console.WriteLine(json);
            }
        }
        /*
        悲观并发：比如有两个用户A,B，同时登录系统修改一个文档，如果A先进入修改，则系统会把该文档锁住
        ，B就没办法打开了，只有等A修改完，完全退出的时候B才能进入修改。

        乐观并发：同上面的例子，A,B两个用户同时登录，如果A先进入修改紧跟着B也进入了。A修改文档的同时
        B也在修改。如果在A保存之后B再保存他的修改，此时系统检测到数据库中文档记录与B刚进入时不一致，
        B保存时会抛出异常，修改失败。
        */
        /// <summary>
        /// 测试EF并发（EF只支持乐观并发，不支持悲观并发）
        /// </summary>
        private static void TestEfConcurrency()
        {
            var strategy = new OrderInitializerForDropCreateDatabaseIfModelChanges();
            Database.SetInitializer<OrderContext>(strategy);

            //取第一条记录,并修改一个字段：这里是修改了Customer
            var context1 = new OrderContext();
            var order1 = context1.Orders.FirstOrDefault();
            if (order1 != null)
            {
                order1.Customer = "Steven";
            }
            //再创建一个Context，同样取第一条记录，修改LastName字段并保存
            using (var context2 = new OrderContext())
            {
                var order2 = context2.Orders.FirstOrDefault();
                if (order2 != null)
                {
                    order2.Customer = "Francis";
                }
                context2.SaveChanges();
            }
            try
            {
                context1.SaveChanges();
                Console.WriteLine(" 保存成功");
            }
            catch (DbUpdateConcurrencyException ex)
            {
                Console.WriteLine(ex.Entries.First().Entity.GetType().Name + " 保存失败");
            }
        }
    }
}

